package com.hliushi.quartz.web;


import com.hliushi.quartz.job.HelloJob;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * @author llhuang10
 * @date 2021/10/24 19:48
 */
@Slf4j
@Api(tags = "动态定时任务")
@RestController
@RequestMapping("/quartz")
public class QuartzController {


    @Resource
    private Scheduler scheduler;


    /**
     * 添加定时任务
     *
     * @param bizId    任务id
     * @param cronExpr cron表达式
     * @return ok
     */
    @PostMapping
    @ApiOperation("添加定时任务")
    public ResponseEntity<String> insertJob(@RequestParam String bizId,
                                            @RequestParam String cronExpr) throws SchedulerException {
        // 1.创建任务实例对象
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
                .withIdentity(bizId)
                .build();

        jobDetail.getJobDataMap().put("bizId", bizId);
        // 2.创建触发器对象
        CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                .withIdentity(bizId)
                .withSchedule(CronScheduleBuilder.cronSchedule(cronExpr)
                        .withMisfireHandlingInstructionDoNothing())
                .build();

        // 关联任务实例和触发器
        scheduler.scheduleJob(jobDetail, cronTrigger);

        return ResponseEntity.ok("ok");
    }

    /**
     * 暂停定时任务
     *
     * @param bizId 任务id
     * @return ok
     */
    @PutMapping("/pause/{bizId}")
    @ApiOperation("暂停定时任务")
    public ResponseEntity<String> pauseJob(@PathVariable String bizId) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(bizId);
        // 暂停指定job的执行
        scheduler.pauseJob(jobKey);
        log.info("JobId : {} 已被暂停", bizId);
        return ResponseEntity.ok("ok");
    }

    /**
     * 恢复定时任务
     *
     * @param bizId 任务id
     * @return ok
     */
    @PutMapping("/resume/{bizId}")
    @ApiOperation("恢复定时任务")
    public ResponseEntity<String> resumeJob(@PathVariable String bizId) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(bizId);
        // 恢复指定job的执行
        scheduler.resumeJob(jobKey);
        log.info("JobId : {} 已被恢复正常运行", bizId);
        return ResponseEntity.ok("ok");
    }

    /**
     * 删除定时任务
     *
     * @param bizId 任务id
     * @return ok
     */
    @DeleteMapping("/{bizId}")
    @ApiOperation("删除定时任务")
    public ResponseEntity<String> deleteJob(@PathVariable String bizId) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(bizId);
        // 删除指定job的执行
        boolean res = scheduler.deleteJob(jobKey);
        if (res) {
            log.info("JobId : {} 已被删除", bizId);
            return ResponseEntity.ok("ok");
        } else {
            log.info("JobId : {} 删除失败", bizId);
            return ResponseEntity.ok("error");
        }
    }


    /**
     * 立即执行定时任务
     *
     * @param bizId 任务id
     * @return ok
     */
    @PutMapping("/run/{bizId}")
    @ApiOperation("立即执行定时任务")
    public ResponseEntity<String> immediatelyRunJob(@PathVariable String bizId) throws SchedulerException {
        JobKey jobKey = JobKey.jobKey(bizId);
        // 立即触发任务, 不管任务的状态是处于 PAUSE(暂停) WAITING(等待执行时间), 调用方法就立即执行
        scheduler.triggerJob(jobKey);
        return ResponseEntity.ok("ok");
    }

    /**
     * 更新定时任务
     *
     * @param bizId    任务id
     * @param cronExpr cron表达式
     * @return ok
     */
    @PutMapping
    @ApiOperation("更新定时任务")
    public ResponseEntity<String> updateJob(@RequestParam String bizId, @RequestParam String cronExpr) throws SchedulerException {
        // 1.触发器的唯一标识
        TriggerKey triggerKey = TriggerKey.triggerKey(bizId);

        // 2.获取原来的触发器
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        // 3.构建新的触发规则
        trigger = trigger.getTriggerBuilder()
                .withIdentity(bizId)
                .withSchedule(CronScheduleBuilder.cronSchedule(cronExpr)
                        .withMisfireHandlingInstructionDoNothing())
                .build();

        // 4.重新按照新的规则进行调度
        scheduler.rescheduleJob(triggerKey, trigger);
        return ResponseEntity.ok("ok");
    }
}
